//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-10-25 23:07
 */
//========================================================================

#ifndef _ASYNCHACCEPTOR_H_
#define _ASYNCHACCEPTOR_H_
#include "Pre.h"

#include "Trace.h"
#include "config.h"
#include "Socket.h"
#include "Proactor.h"
#include "AsynchIO.h"
#include "MessageBlock.h"

class InetAddr;
class Proactor;

/**
 * @class AsynchAcceptor
 *
 * @brief This class is an example of the Acceptor Pattern.  This class
 * will accept new connections and create new HANDLER to handle
 * the new connections.
 */
template<typename HANDLER>
class AsynchAcceptor : public AsynchHandler
{
public:
    // A do nothing constructor.
    AsynchAcceptor ();

    //
    virtual ~AsynchAcceptor ();

    /**
     * open starts one or more asynchronous accept requests on a
     * address. Each accept operation may optionally read an
     * initial buffer from the new connection when accepted.
     *
     * If <num_of_accepts_one_time> equal -1, then assign <backlog> 
     * to it, <num_of_accepts_one_time> is very useful, it can 
     * decrease the aio-system-call.
     * On Windows, the peer address is only available at the time
     * the connection is accepted. Therefore, if you require the peer
     * address on Windows, do not rely on the Sock::get_remote_addr() 
     * method - it won't work. You can obtain the peer address in the 
     * ServiceHandler::addresses() method.
     */
    virtual int open (const InetAddr &address,
	    Proactor *proactor = Proactor::instance (),
	    int reuse_addr = 1,
	    size_t rcvbuf_size = 0,
	    int protocol_family = AF_INET,
	    int backlog = NDK_DEFAULT_BACKLOG,
	    int num_of_accepts_one_time = -1);

protected:
    // This is called when an outstanding accept completes.
    virtual int handle_accept (const AsynchAccept::Result &result);

    virtual int handle_close (const int mask);

    // Return the listen handle.
    virtual NDK_HANDLE handle (void) const;

    /**
     * This is the template method used to create new handler.
     * Subclasses must overwrite this method if a new handler creation
     * strategy is required.
     */
    virtual HANDLER *make_handler (void);
private:
    // Handle used to listen for new connections.
    NDK_HANDLE listen_handle_;

    int num_of_accepts_one_time_;

    // 
    AsynchAccept asynch_accept_;
};

#include "AsynchAcceptor.cpp"
#include "Post.h"
#endif

